/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package project1;

import java.util.ArrayList;
import java.util.HashMap;

/**
 *
 * @author rr
 */
public class ConstraintChecker {

    private static ConstraintChecker instance = null;
    private ArrayList<Constraint> contraints;

    private ConstraintChecker() {
        contraints = new ArrayList<Constraint>();
    }

    public static ConstraintChecker getInstance() {
        if (instance == null) {
            instance = new ConstraintChecker();
        }
        return instance;
    }

    public int[] updatePossibleAssignments(boolean[][] oldPossibleAssignments, int[] tempAssignments) {

        boolean tempBool;
        
        
        int mostConstrainedVariableIndex = -1;
        int minimumPossibleValuesForVariableCount = Integer.MAX_VALUE;
        
        int possibleValuesForVariableCount = 0;
        
        int possibleVariablesCount = 0;
        
        boolean nextVariableFound = false;
        
        //the rows (i) are possible values the columns (ninja) are variables
        for (int j = 0; j < oldPossibleAssignments[0].length; ++j) {
            if(!nextVariableFound){
                //we are looking for the next assignment to make
                possibleValuesForVariableCount = 0;
            }
            for (int i = 0; i < oldPossibleAssignments.length; ++i) {
                if(oldPossibleAssignments[i][j] == true){ //check only possible values
                    tempBool = true;
                    for (int k = 0; k < this.contraints.size() && tempBool; ++k) {
                        //as soon as one constraint does not permit this assignment we set it to false and we're done
                        tempBool = tempBool && this.contraints.get(k).check(tempAssignments, j, i);
                    }
                    //set false or true
                    oldPossibleAssignments[i][j] = tempBool;   
                    if(tempBool && !nextVariableFound){
                        if(possibleValuesForVariableCount == 0){
                            ++possibleVariablesCount;
                        }
                        //we could assign this value - add 1 to the possibleValuesCount for this variable
                        ++possibleValuesForVariableCount;
                    }
                }
            }
            if(possibleValuesForVariableCount>0){
             if(possibleValuesForVariableCount < minimumPossibleValuesForVariableCount && !nextVariableFound){
                //if there are possible assignments && there are fewer possible assignments than for the variables so far && we did not find a assignment variable yet
                minimumPossibleValuesForVariableCount = possibleValuesForVariableCount;
                mostConstrainedVariableIndex = j;
                
                if(minimumPossibleValuesForVariableCount == 1){
                    //if we have a variable with only 1 possible value we take it! GREED IS GOOD
                    nextVariableFound = true;
                }
            }}
            else if(tempAssignments[j]==-1){
                //solution is doomed
                return null;
                
            }
            
        }
        
           
        int returnValue[] = {mostConstrainedVariableIndex,minimumPossibleValuesForVariableCount};
        
        return returnValue;
    }

    public ArrayList<Constraint> getContraints() {
        return contraints;
    }

    public void setContraints(ArrayList<Constraint> contraints) {
        this.contraints = contraints;
    }

    public ConstraintChecker getCopy() {
        
        ConstraintChecker returnInstance = new ConstraintChecker();
        Constraint aConstraint = new TemporalRequirementsConstraint();
        returnInstance.getContraints().add(aConstraint);
        Constraint seqConstraint=new SequencesConstraint();
        returnInstance.getContraints().add(seqConstraint);
        Constraint blockConstraint=new BlockLengthConstraint();
        returnInstance.getContraints().add(blockConstraint);
        return returnInstance;
        
    }
}
